package com.szsh.aiot.hsm.thirdService;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.szsh.aiot.hsm.dto.ability.NetTopInfo;
import com.szsh.aiot.hsm.dto.ehoHome.IEhomeCamera;
import com.szsh.aiot.hsm.dto.ehoHome.EHomeReq;
import com.szsh.aiot.hsm.dto.ehoHome.EHomeResp;
import com.szsh.aiot.hsm.dto.ehoHome.LiveAndLookBack;
import com.szsh.aiot.hsm.dto.ehoHome.LiveAndLookBackItems;
import com.szsh.aiot.hsm.utils.AESUtil;
import com.szsh.aiot.hsm.utils.SignUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.security.SecureRandom;
import java.util.*;

/**
 * 天翼看家卫士中通过phone查询摄像头信息的接口客户端封装
 */
@Component
public class EHomeClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(EHomeClient.class);
    private static final Random RAND = new SecureRandom();;

    @Value("${hsm.ehome.appKey}")
    private String appKey;
    @Value("${hsm.ehome.appSecret}")
    private String appSecret;
    @Value("${hsm.ehome.version}")
    private String version;
    @Value("${hsm.ehome.clientType}")
    private int clientType;
    @Value("${hsm.ehome.baseUrl}")
    private String baseUrl;
    @Value("${hsm.ehome.getCameraPhoneInfo}")
    private String getCameraPhoneInfo;
    @Value("${hsm.ehome.getLiveAndLookBack}")
    private String getLiveAndLookBack;

    private final RestTemplate restTemplate;

    public EHomeClient(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    private final Gson gson = new Gson();

    /**
     * 通过phone查询用户绑定的摄像头设备
     * @param phone 用户手机号
     * @return
     */
    public List<IEhomeCamera> getCameraPhoneInfo(String phone){
        List<IEhomeCamera> rspBody = new ArrayList<>();
        try{
            Map<String,String> paramMap = new HashMap<>();
            paramMap.put("phone",phone);
            EHomeReq req = getEHomeRequestBody(gson.toJson(paramMap),getCameraPhoneInfo);
            LOGGER.info("getCameraPhoneInfo Req phone[{}], body[{}]",phone, req.toString());
            String url = baseUrl+getCameraPhoneInfo;
            LOGGER.info("getCameraPhoneInfo Req phone[{}], URL[{}]",phone, url);
            EHomeResp rsp = restTemplate.postForObject(url, req,EHomeResp.class);
            if (Objects.isNull(rsp) || rsp.getCode() != 0) {
                return rspBody;
            }
            LOGGER.info("getCameraPhoneInfo phone[{}], EHomeResp[{}]",phone,rsp.toString());
            String dataListAesStr = rsp.getDatalist();
            if (StringUtils.isNotBlank(dataListAesStr)) {
                String IV = appSecret.substring(16,32);
                String dataListStr = AESUtil.decryptCbcWithIv(dataListAesStr,appSecret,IV);
                LOGGER.info("getCameraPhoneInfo dataListStr{}",dataListStr);
                rspBody = gson.fromJson(dataListStr, new com.google.common.reflect.TypeToken<List<IEhomeCamera>>() {}.getType());
            }
        }catch (Exception e){
            LOGGER.error("调用通过phone查询用户绑定的摄像头设备报错[{}]",phone,e);
        }
        return rspBody;
    }

    /**
     * 新增用户查看直播、云回看记录,对方接口要求分页查询
     * @param deviceCode 设备码
     * @param beginTime 开始时间
     * @param endTime  结束时间
     * @param page 页码
     * @param pageSize  条数 默认10
     * @return
     */
    public LiveAndLookBack getLiveAndLookBack(String deviceCode,
                                              String beginTime, String endTime, int page, int pageSize){
        try{
            Map<String,Object> paramMap = new HashMap<>();
            paramMap.put("deviceCode",deviceCode);
            paramMap.put("beginTime",beginTime);
            paramMap.put("endTime",endTime);
            paramMap.put("page",page+"");
            paramMap.put("pageSize",pageSize+"");
            EHomeReq req = getEHomeRequestBody(gson.toJson(paramMap),getLiveAndLookBack);
            LOGGER.info("getLiveAndLookBack Req deviceCode[{}], body[{}]",deviceCode, req.toString());
            String url = baseUrl+getLiveAndLookBack;
            LOGGER.info("getLiveAndLookBack Req deviceCode[{}], URL[{}]",deviceCode, url);
            String rsp = restTemplate.postForObject(url, req,String.class);
            LOGGER.info("getLiveAndLookBack deviceCode[{}], EHomeResp[{}]",deviceCode,rsp);
            EHomeResp eHomeResp = gson.fromJson(rsp,EHomeResp.class);
            LOGGER.info("getLiveAndLookBack respResult[{}]",eHomeResp.toString());
            if(Objects.isNull(eHomeResp) || eHomeResp.getCode() != 0){
                return null;
            }
            LiveAndLookBack liveAndLookBack = eHomeResp.getResult();
            if(Objects.isNull(liveAndLookBack)) return null;
            String itemsAes = liveAndLookBack.getItems();
            if (StringUtils.isNotBlank(itemsAes)) {
                String IV = appSecret.substring(16,32);
                String itemsStr = AESUtil.decryptCbcWithIv(itemsAes,appSecret,IV);
                LOGGER.info("getLiveAndLookBack itemsStr{}",itemsStr);
                gson.fromJson(gson.toJson(itemsStr),new TypeToken<List<LiveAndLookBackItems>>() {}.getType());
                List<LiveAndLookBackItems> liveAndLookBackItems =
                        gson.fromJson(gson.toJson(itemsStr),new TypeToken<List<LiveAndLookBackItems>>() {}.getType());;
                liveAndLookBack.setLiveAndLookBackItems(liveAndLookBackItems);
            }
            return liveAndLookBack;
        }catch (Exception e){
            LOGGER.error("新增用户查看直播或者云回看记录报错[{}]",deviceCode,e);
        }
        return null;
    }

  /**
   * 入参params加密前需要拼接 data=
   * @param paramsStr
   * @param method
   * @return
   * @throws Exception
   */
  private EHomeReq getEHomeRequestBody(String paramsStr, String method) throws Exception {
      paramsStr = "data="+paramsStr;
      LOGGER.info("入参中params[{}]",paramsStr);
      EHomeReq req = new EHomeReq();
      req.setMethod(method);
      req.setAppKey(appKey);
      req.setClientType(clientType);
      req.setVersion(version);
      String nonce = randomHexString(16);
      req.setNonce(nonce);
      Long timestamp = System.currentTimeMillis()/1000;
      req.setTimestamp(timestamp);
      String IV = appSecret.substring(16,32);
      String params = AESUtil.encryptCbcWithIv(paramsStr,appSecret,IV);
      String signatureStr = "appKey"+appKey+"clientType"+clientType+"method"+method
               +"nonce"+nonce+"params"+params+"timestamp"+timestamp+"version"+version;
      String signature = SignUtils.hmacEncode(signatureStr,appSecret);
      req.setParams(params);
      req.setSignature(signature);
      return req;
  }

    /**
     * 获取16进制随机数
     *
     * @param len
     * @return
     */
    public static String randomHexString(int len) {
        try {
            StringBuffer result = new StringBuffer();
            for (int i = 0; i < len; i++) {
                result.append(Integer.toHexString(RAND.nextInt(16)));
            }
            return result.toString();
        } catch (Exception e) {
            throw new RuntimeException("create random Failed ", e);
        }

    }
}
